/*------------------------------------------- Noble Steed Engine-------------------------------------*
Authors : Daniel Randle, Alex Bourne
Date Created : Mar 10 2013

File:
	nsmaterial.cpp

Description:
	This file contains the definition for the NSMaterial class along with any helper functions
	that the class may use
*--------------------------------------------------------------------------------------------------*/

#include <nsmaterial.h>
#include <nstexture.h>
#include <sstream>
#include <logfile.h>

NSMaterial::NSMaterial(NSTexture * diffuseMap, 
	NSTexture *  normalMap,  
	NSTexture *  specularMap,  
	NSTexture *  displacementMap,  
	NSTexture *  heightMap,  
	NSTexture *  ambientMap,  
	NSTexture *  emissiveMap,  
	NSTexture *  shininessMap,  
	NSTexture *  opacityMap,  
	NSTexture *  lightMap,  
	NSTexture *  reflectionMap):
	TextureMapTypes(TEXMAPTYPES),
	alphaBlend(false)
{
	LogFile("Creating new material..");
	textures.push_back(diffuseMap);
	textures.push_back(specularMap);
	textures.push_back(ambientMap);
	textures.push_back(emissiveMap);
	textures.push_back(heightMap);
	textures.push_back(normalMap);
	textures.push_back(shininessMap);
	textures.push_back(opacityMap);
	textures.push_back(displacementMap);
	textures.push_back(lightMap);
	textures.push_back(reflectionMap);
}

NSMaterial::~NSMaterial()
{
	LogFile("Deleting material and its textures..");
	int count = textures.size()-1;
	while (textures.begin() != textures.end())
	{
		std::stringstream ss;
		if (textures.back() != NULL)
		{
			ss << "Found texture using texture unit " << count;
			LogFile l(ss);
		}
		delete textures.back();
		textures.pop_back();
		--count;
	}
	LogFile("Material Deleted");
}

NSTexture * NSMaterial::getTexture(NSTexture::MapType mapType)
{
	return textures[mapType];
}

bool NSMaterial::isAlphaBlend()
{
	return alphaBlend;
}

bool NSMaterial::loadTextureFromFile(const std::string & fileName, 
	const std::string & textureDir,
	NSTexture::MapType mapType,
	bool mipmap,
	NSTexture::TexType type)
{
	bool ret = true;

	NSTexture * toAddTex = new NSTexture(mapType);
	LogFile l("Set texture file to : " + fileName);
	if (toAddTex->loadFromFile(fileName, textureDir, mipmap, type)) 
	{
		setTexture(mapType,toAddTex,true);
		l.write("Mesh successfully loaded texture in to material");
    }
	else
	{
        l.write("Error in mesh loading texture in to material");
		delete toAddTex; // Delete texture because it didn't load correctly
		ret = false;
	}
	return ret;
}

void NSMaterial::setAlphaBlend(bool set)
{
	alphaBlend = set;
}

bool NSMaterial::setTexture(NSTexture::MapType mapType, NSTexture * texture, bool overwrite)
{
	if (textures[mapType] != NULL)
	{
		LogFile("Called setTexture in Material with mapType that already has texture");
		if (overwrite)
		{
			LogFile("Overwriting texture with new texture - overwrite true specified");
			LogFile("Overwriting texture with filename : " + textures[mapType]->getFilename());
			delete textures[mapType];
			textures[mapType] = texture;
			return true;
		}
		return false;
	}
	textures[mapType] = texture;
	return true;
}

void NSMaterial::disableAllValidTextures()
{
	std::vector<NSTexture*>::iterator iter = textures.begin();
	while (iter != textures.end())
	{
		if (*iter != NULL)
			(*iter)->disable();
		++iter;
	}
}

void NSMaterial::disableTexture(NSTexture::MapType mapType)
{
	textures[mapType]->disable();
}

void NSMaterial::useAllValidTextures()
{
	std::vector<NSTexture*>::iterator iter = textures.begin();
	while (iter != textures.end())
	{
		if (*iter != NULL)
			(*iter)->use();
		++iter;
	}
}

void NSMaterial::useTexture(NSTexture::MapType mapType)
{
	textures[mapType]->use();
}